package com.xx;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.topsoft.topdp.mybatis.entity.StringIdExtendEntity;
import com.topsoft.topdp.mybatis.mapper.TopDpBaseMapper;
import com.topsoft.topdp.mybatis.service.TopDpBaseService;
import com.topsoft.topdp.mybatis.service.impl.TopDpBaseServiceImpl;
import com.xx.lib.EnhanceFreemarkerTemplateEngine;
import org.junit.Test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * https://baomidou.com/pages/779a6e/ 新
 * <p>
 * https://baomidou.com/pages/d357af/ 旧（参数详解）
 * <p>
 * 自定义模板有哪些可用参数？Github (opens new window)AbstractTemplateEngine 类中方法 getObjectMap 返回 objectMap 的所有值都可用。
 */
public class Generator {

    /**
     * 生成的文件存放路径
     * 原文链接：https://blog.csdn.net/TimerBin/article/details/127799360
     * <p>
     * System.getProperty("user.dir"); 获取当前模块所在的路径
     */
    private static final String FILE_STORAGE_FILE_ROOT_PATH = System.getProperty("user.dir") + "\\generator\\src\\main\\java";
    /**
     * 生成的mapper.xml 文件存放地址
     */
    private static final String FILE_STORAGE_MAPPER_XML_FILE_JAR_PACKAGE = System.getProperty("user.dir") + "\\generator\\src\\main\\resources\\mapper\\";
    /**
     * 数据源配置
     */
    private static final DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig
            .Builder("jdbc:postgresql://172.25.2.101:5432/six_one_portal", "postgres", "postgres").schema("public");

    /**
     * 执行 run
     */
    public static void main(String[] args) {
        FastAutoGenerator.create(DATA_SOURCE_CONFIG)
                .globalConfig(builder -> {
                    // 设置作者
                    builder.author("xuyanqing")
                            // 开启 swagger 模式
                            .enableSwagger()
                            // 覆盖已生成文件
                            .fileOverride()
                            // 禁止打开输出目录
                            .disableOpenDir()
                            // 指定输出目录
                            .outputDir(FILE_STORAGE_FILE_ROOT_PATH)
                            // 时间策略
                            .dateType(DateType.TIME_PACK)
                            // 时间格式
                            .commentDate("yyyy-MM-dd");
                })

                // https://blog.csdn.net/zhangHP_123/article/details/126061630
                .packageConfig(builder -> {
                    // 设置父包名
                    builder.parent("org.topsoft.topdap")
                            // 设置父包模块名
//                            .moduleName("metadata")
                            // 实体类包名
                            .entity("entity")
                            // service包名
                            .service("service")
                            // serviceImpl包名
                            .serviceImpl("service.impl")
                            .mapper("dao")
                            // 指定xml生成的路径
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, FILE_STORAGE_MAPPER_XML_FILE_JAR_PACKAGE));
                })
                .strategyConfig(builder -> {
                    // 设置需要生成的表名
                    builder.addInclude("dap_report_info","dap_standard", "dap_report_role", "dap_report_sign", "dap_sign_base", "dap_sign_base_group","dap_standard_group","dap_unit","dap_unit_group")
//                            .addTablePrefix("nqi_", "c_")
                            // 自定义配置继承父包 HmBaseMapper  此类为我们公司扩展类
                            .mapperBuilder()
                            .superClass(TopDpBaseMapper.class)
                            .enableBaseColumnList()
                            .enableBaseResultMap()
                            // 如果不设置，如表[sys_user]，默认的文件名是[SysUserMapper]。写成下面这种形式后，将变成[SysUserDao]
                            .formatMapperFileName("%sDao")
                            .build()

                            // 实体类配置
                            .entityBuilder()
                            // 会在实体类前添加 [@Getter] 和 [@Setter] 注解。（这是Lombok的注解，需要添加Lombok依赖）
                            .enableLombok()
                            .enableTableFieldAnnotation()
//                            .enableChainModel()
                            .superClass(StringIdExtendEntity.class)
                            // 数据库表字段映射到实体的命名策略，下划线转驼峰命名
                            .columnNaming(NamingStrategy.underline_to_camel)
                            // 这些字段不会出现在新增的实体类中。
                            .addSuperEntityColumns("id", "deleted", "row_state", "update_time")
                            // 会在实体类前添加 [@Accessors(chain = true)] 注解。用法如 [User user=new User().setAge(31).setName("snzl");]（这是Lombok的注解，需要添加Lombok依赖）
                            .enableChainModel()
                            .enableTableFieldAnnotation()
//                            .disableSerialVersionUID()
                            .build()

                            // service配置
                            .serviceBuilder()
                            .superServiceClass(TopDpBaseService.class)
//                            .superServiceClass(IService.class)
                            .superServiceImplClass(TopDpBaseServiceImpl.class)
//                            .superServiceImplClass(ServiceImpl.class)

                            // controller配置
                            .controllerBuilder()
                            // 开启生成@RestController 控制器
                            .enableRestStyle()
                            // 开启驼峰转连字符
                            .enableHyphenStyle()
//                            .convertFileName()
                            .build();

                })
                .injectionConfig(consumer -> {
                    Map<String, String> customFileMap = new HashMap<>(4);
                    // DTO 下面的key会作为类名后缀，进而生成新类
                    customFileMap.put("Dto.java", "templates/other/dto.java.ftl");
                    customFileMap.put("Vo.java", "templates/other/vo.java.ftl");
//                    customFileMap.put("dto"+ File.separator+"%s.java", "templates/other/dto.java.ftl");
//                    customFileMap.put("vo"+File.separator+"%s.java", "templates/other/vo.java.ftl");
                    customFileMap.put("Convertor.java", "templates/other/convertor.java.ftl");
                    consumer.customFile(customFileMap);
                })
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
//                .templateEngine(new FreemarkerTemplateEngine())
                // 解决DTO,VO类生成的路径和文件名问题
                .templateEngine(new EnhanceFreemarkerTemplateEngine())
                .execute();

    }

    @Test
    public void generatorTest() {

        // 定位
        String finalProjectPath = System.getProperty("user.dir");
        System.out.println(finalProjectPath);

        // 执行
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8", "root", "root").globalConfig(builder -> {
                    builder.author("kanan") // 设置作者
                            .fileOverride().enableSwagger() // 开启 swagger 模式
                            .disableOpenDir() //禁止打开输出目录
                            .outputDir(finalProjectPath + "/src/main/java"); // 指定输出目录
                }).packageConfig(builder -> {
                    builder.parent("com.xx") // 设置父包名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, finalProjectPath + "/src/main/resources")); // 设置mapperXml生成路径
                }).strategyConfig(builder -> {
                    // 需要被解析的表名
                    builder.addInclude("auth_permission");
                    builder.entityBuilder().enableLombok().enableTableFieldAnnotation();
                    builder.controllerBuilder().enableRestStyle();
                }).injectionConfig(consumer -> {
                    Map<String, String> customFile = new HashMap<>();
                    // DTO 下面的key会作为类名后缀，进而生成新类
                    customFile.put("DTO.java", "templates/other/dto.java.ftl");
                    customFile.put("VO.java", "templates/other/vo.java.ftl");
                    customFile.put("Convertor.java", "templates/other/convertor.java.ftl");
                    consumer.customFile(customFile);
                })
                // EnhanceFreemarkerTemplateEngine 里主要重写对自定义类的处理 如vo dto convert等
                .templateEngine(new EnhanceFreemarkerTemplateEngine()).execute();
    }
}
